ICTSC2020 インフラ解説 ネットワーク編

今回、ネットワークの設計を行ったえると(@proelbtn)です。

今回のトポロジ

今回は、以下のような構成でネットワークを構築しました。

今回の構成

今回、ネットワーク側では、以下のような試みをしました。

  1. 対外接続冗長化 + フルルート受信した
  2. サーバとコアスイッチ間を10Gbpsで接続した
  3. NAVT用にP4スイッチを用意した
  4. VPN接続にWireGuardを利用した

この章では、これらの試みについて簡単に説明をしていきたいと思います。

1. 対外接続冗長化 + フルルート受信

今回もコロナウイルスの影響により、オンラインで本戦が開催されるだろうという話がありました。そのため、トランジットを提供してくださっているHomeNOCの東京・大阪の2拠点と接続を行いました。

東京回線の方は、NGN網内折返し通信 + EtherIPを利用して東京の拠点であるPOP03と接続を行いました。大阪回線の方は、NGN網内だけで到達することができないため、プロバイダーを経由して大阪の拠点であるNOC51とIPIPトンネルを張り接続を行いました。そのため、東京回線のLocal Preference値をデフォルトの100から200にして、パケットを送出する際は出来る限り東京回線を経由して通信を流すように設定しました。

実際に、パケットの流量を確認してみると、大阪回線の方のTXはほとんどないことが分かります。少しだけ通信を行っているのはBGPの通信が発生しているためだと考えられます。また、東京回線・大阪回線共に、2日目のRXが大きくなっていることが分かります。これらの詳しい理由については分かっていませんが、トラコンでは2日間で出題する問題が異なるため、このような傾向が見られたのではないかなと考えています。

2. サーバとコアスイッチ間を10Gbpsで接続した

今回は仮想化基盤側でCeph RBDを利用してVMのブロックストレージを用意するという試みを行いました。ネットワーク通信の部分がディスクのR/Wのボトルネックにならないようにするために、全てのサーバ間を10Gbpsで接続しました。昨年は、サーバー数が多かったため、一部のVMのみ10GbpsのNICを搭載させましたが、今年は高密度に問題VMを展開したため、全サーバーに10GbpsのNICを搭載して接続することができました。

実際に、問題VMを展開してみると、最大で400MB/s程度の帯域を利用していることが分かりました。

3. NAVT用にP4スイッチを用意した

今回NAVTの実装を行った @takemioIOです。
ICTSCにおいて問題VMの展開を容易にするためにNAVTと呼ばれるアドレス変換の仕組みを導入しています。Network Address Vlan Translation (NAVT)はアドレス変換(NAT)を行う際にvlanをkeyにしたアドレス変換のことを指しており、具体的にはinside側のアドレスvlanキーにしてoutside側から見たときにはvlan idをipアドレスに含ませて一意にステートレス変換をすることができる技術です。

e.g. VID:100, 192.168.0.1(inside) <=> 10.1.0.1 (outside)

これらを利用することで内部側で利用するアドレス空間はvlan idが異なるだけで全て同じアドレスを利用することができます。それによってコンテストにおいて、vlan idを参加チームごとに割り当てることでアドレス環境を全てのチームすることができ環境の差異をなくすことができる嬉しさがあります。

今回はP4と呼ばれる言語で実装を定義し、Tofinoと呼ばれるASICを利用してNAVTを作りました。またこれを導入したことでトラコン初の100Gbps接続を達成しました。

簡単に実装および利用した感想を述べます。
P4が動くソフトウェアスイッチの実装としてBMv2と呼ばれるOSSで公開されているリファレンス実装があり、それターゲットに事前に実装を行い、それをTofino向けに移植する形で実装を行いました。

BMv2向けに動作ができる拙作の実装がこちらになります https://github.com/takehaya/p4-navt
残念ながらTofino向けの実装したものはライセンスの都合上公開することができませんが、P4がどのようなものなのかを理解するには十分なリファレンスになると思います。

さて、この移植がかなり大変でした。まずASICごとにP4で作られるアーキテクチャが異なります。パケット処理なのでパイプラインというものがありますがその定義や変数の取り扱いなどはいくつも異なるのです。

皆さんになじみやすい例え方としてはウェブアプリケーションのフレームに似ているかもしれません。例えばRailsなど有名なものが大体MVCを基礎として作られていますがクラスの作り方やバリデーションには細かい差異があると思います。P4でも同じように大枠の仕組みは同じですがアーキテクチャと呼ばれる構造が微妙に異なります。今回はv1modelというBMv2に採用されているアーキテクチャとTofino Native Architecture(TNA)と呼ばれるTofinoに採用されているアーキテクチャが異なる部分になり大変だった理由の一つでした。今回はそれを上手いこと実装で違いを補わなくてはいけない訳です。

ちなみにですが TNAについての定義ファイルは https://github.com/barefootnetworks/Open-Tofino に公開されているのでこちらを参照すると雰囲気が伝わります。

さらには表現力も異なります。例えばbitshiftが事実上Tofinoだとまともに使いこなせないのでできるだけTableを使ったシンプルな構成で実装をすると移植がしやすかったなと思いました。
またP4Runtimeと呼ばれるCPU処理に移譲するインターフェースがあるのですがそれを使ってARPリプライなどをBMv2ターゲットでは用意していました。しかしTofinoターゲットでは別のRuntimeが存在しそちらでなければ動かない機能などがあり完全にAPIのインターフェースごと変える必要が出てしまったために今回の対応スコープからは一旦落とすことにしました。

デバッグを行う際も大変でした。まず実機ではASICを通して処理をする故にtcpdumpが使えない訳です。またエミュレーターが提供されているのでそれで通信を眺めようとすると生パケットをコンソールにただ出してくるので目でhexを見ることになり一時期はL3までを目が慣れてしまい目でデコードしていました…

と、まだまだ辛かった話は存在するのですが一方使いこなすと非常にお手軽に100Gbps以上の性能をソフトウェアで定義しつつ引き出すことができるのは大変素晴らしいと思いました。実際XDP, DPDKなどではIRQ, CPUアフィニティを意識したりCPUコアを増やしてRSSを効かせるなどいろんなチューニングを意識する必要があり大変ですが、このような部分を無視して実装を書くことができるのは素晴らしく今後普及していくのだろうなと感じました。
実際利用した側としては安定感ももちろん素晴らしく、ホットステージを含め本戦期間中一度もSwitchが落ちることがなく動作しました。

最後になりますが機材スポンサーとして提供してくださったAPRESIA SYSTEMS様本当にありがとうございました。P4を利用した実装をはじめたいと思う方の参考になれば幸いです。

4. VPN接続にWireGuardを利用した

最後の試みは、VPN接続にWireGuardを利用した点です。ICTSCでは、外部から会場ネットワークに接続するためや監視基盤が動いているさくらのクラウドとのサイト間接続のためにVPNを利用しています。前回は、外部から会場ネットワークに接続するためにはOpenVPNを、さくらのクラウドとのサイト間接続にはIPsecを利用していました。ですが、前回はIPsecの接続に時間がかかりクラウド上の監視基盤がうまく利活用されなかったりという問題がありました。

そのため、今回はVPN接続にWireGuardを利用しました。WireGuardは様々なOS上で実装されているL3VPNの実装で、IPsecを超えるパフォーマンスとOpenVPN並みの接続の容易さを兼ね揃えたVPNの実装です。主に、リモートから作業をする運営用のVPN接続とクラウドに構築されている監視基盤との接続を行うために利用しています。リモートから作業する運営用のVPN接続では、30クライアントほど設定を行っていましたが、通信が遅くて困るということはなく利用できました。

また、クラウドとの接続では、BGP over WireGuardをして監視基盤との接続性を提供しました。監視基盤側では、Kubernetesのtype: LoadBalancerの機能を提供してくれるMetalLBを利用しており、MetalLBが広報している経路が直接会場側で受けていました。実際に、IPsecの代わりに使っても性能的に問題なく、設定も遥かに楽なのでとても良かったと思います。

起きたトラブル

Docker HubのRate Limitに引っかかる

今回、問題の中でDockerイメージをpullするような問題がありました。そのため、多くのチームが docker pull を実行することでrate limitに引っかかってしまったという問題です。

Docker Hubのrate limitはIPアドレスベースでかかるため、参加者ネットワークからインターネットに抜ける通信用のpoolを大きくしてあげることで対処しました。もう少しこの問題が予見されていたら、ローカルにリポジトリを立てて対策をすればよかったですが、完全にrate limitの存在を忘れていました。

以下は、実際にSRXに入れた設定なのですが、頑張ってIPアドレスをかき集めてきた様子が分かると思います。